<template>
  <!-- showScroll 控制滚动条显示与否 -->
  <div class="scrollBox-work" v-if="showScroll">
    <!-- scrollBox-track-work 定义轨道 -->
    <div class="scrollBox-track-work">
      <!-- scrollBox-thumb-work 定义滑轮 -->
      <div class="scrollBox-thumb-work"></div>
    </div>
  </div>
</template>

<script>
export default {
  name: "ScrollBar",
  props: {
    targetEle: {
      type: HTMLDivElement,
    },
  },
  data() {
    return {
      // 注销事件对象
      removeEvent: null,
      showScroll: false,
      // ref方式调用时保存的滚动元素dom
      refTargetEle: null,
    };
  },
  mounted() {
    // 页面尺寸改变时，需要重新获取滚动
    window.addEventListener("resize", this.resizeFun);
  },
  beforeDestroy() {
    // 组件注销时，移除监听事件
    this.removeEvent ? this.removeEvent() : null;
    window.removeEventListener("resize", this.resizeFun);
  },
  methods: {
    // 主逻辑部分
    addScrollEvent(targetEle = this.targetEle) {
      if (!this.targetEle) this.refTargetEle = targetEle;
      if (targetEle) {
        const targetEleWidth = targetEle.clientWidth;
        const scrollWidth = targetEle.scrollWidth;
        this.showScroll = targetEleWidth >= scrollWidth ? false : true;
        this.$nextTick(() => {
          if (this.showScroll) {
            const scrollEle = document.getElementsByClassName(
              "scrollBox-thumb-work"
            )[0];
            const scrollTrackEle = document.getElementsByClassName(
              "scrollBox-track-work"
            )[0];
            // 轨道宽度
            const trackWidth = scrollTrackEle.clientWidth;
            // 滑轨宽度
            const thumbWidth = scrollEle.clientWidth;
            const defaultScrollLeft = scrollWidth - targetEleWidth;
            // 鼠标拖拽移动
            // 初始页面位置
            let startX = null;
            // 滑轨初始位置
            let startLeft = null;
            // start
            scrollEle.addEventListener("mousedown", startEvent);
            targetEle.addEventListener("scroll", scrollEvent);
            // event
            function startEvent(e) {
              e.preventDefault();
              startX = e.pageX;
              startLeft = scrollEle.offsetLeft;
              document.addEventListener("mousemove", moveEvent);
              document.addEventListener("mouseup", stopEvent);
            }
            function moveEvent(e) {
              // 鼠标移动距离
              const deltaY = e.pageX - startX;
              // 滑轨新的位置
              const newLeft = Math.max(
                0,
                Math.min(trackWidth - thumbWidth, startLeft + deltaY)
              );
              // 滚动元素位置
              const scrollLeft =
                (newLeft / (trackWidth - thumbWidth)) *
                (scrollWidth - targetEleWidth);

              targetEle.scrollLeft = scrollLeft;
              scrollEle.style.left = newLeft + "px";
            }

            function scrollEvent() {
              const { scrollLeft, clientWidth, scrollWidth } = targetEle;
              const thumbLeft =
                (scrollLeft / (scrollWidth - clientWidth)) *
                (trackWidth - thumbWidth);
              scrollEle.style.left = thumbLeft + "px";
            }

            // 鼠标滚轮
            // 注册滚动事件处理程序
            if ("onmousewheel" in targetEle) {
              targetEle.onmousewheel = handleMouseWheel; // Chrome/Safari/Opera等非IE浏览器
            } else if ("DOMMouseScroll" in targetEle) {
              targetEle.addEventListerner(
                "DOMMouseScroll",
                handleMouseWheel,
                false
              ); // Firefox浏览器
            } else {
              targetEle.addEventListener(
                "MozMousePixelScroll",
                handleMouseWheel,
                false
              ); // IE浏览器
            }
            function handleMouseWheel(e) {
              if (e.deltaX !== 0) {
                e.preventDefault();
                e = e || window.event; // 兼容不同浏览器
                let deltaX = Math.max(
                  -1,
                  Math.min(1, e.wheelDeltaX || -e.deltaX)
                ); // 计算滚动量
                let startLeft = scrollEle.offsetLeft;
                let speed =
                  (defaultScrollLeft > 200 ? defaultScrollLeft : 200) / 200;
                const newLeft = Math.max(
                  0,
                  Math.min(trackWidth - thumbWidth, startLeft - speed * deltaX)
                );
                // 滚动元素位置
                const scrollLeft =
                  (newLeft / (trackWidth - thumbWidth)) * defaultScrollLeft;

                targetEle.scrollLeft = scrollLeft;
              }
            }

            // 注销事件
            function removeEvent() {
              document.removeEventListener("mousemove", moveEvent);
              document.removeEventListener("mouseup", stopEvent);
              scrollEle.removeEventListener("mousedown", startEvent);
              targetEle.removeEventListener("scroll", scrollEvent);
              if ("onmousewheel" in targetEle) {
                targetEle.onmousewheel = null; // Chrome/Safari/Opera等非IE浏览器
              } else if ("DOMMouseScroll" in targetEle) {
                targetEle.removeEventListener(
                  "DOMMouseScroll",
                  handleMouseWheel
                ); // Firefox浏览器
              } else {
                targetEle.removeEventListener(
                  "MozMousePixelScroll",
                  handleMouseWheel
                ); // IE浏览器
              }
            }
            this.removeEvent = removeEvent;
          }
        });
      }
    },
    stopEvent() {
      document.removeEventListener("mousemove", moveEvent);
      document.removeEventListener("mouseup", stopEvent);
    },
    resizeFun() {
      this.targetEle
        ? this.addScrollEvent()
        : this.addScrollEvent(this.refTargetEle);
    },
  },
};
</script>

<style lang="scss" scoped>
.scrollBox-work {
  width: 100%;
  justify-content: center;
  align-items: center;
  display: flex;
  transition: 0.1s all;
  margin-top: 20px;
  .scrollBox-track-work {
    position: relative;
    width: 76px;
    height: 6px;
    background-color: #f2f3f5;
    border-radius: 3px;
    .scrollBox-thumb-work {
      width: 47px;
      height: 6px;
      background-color: #3270ff;
      border-radius: 3px;
      position: absolute;
      left: 0;
    }
  }
}
</style>